package com.micolor.logr.runtime.aspect;

import com.micolor.logr.runtime.annotation.LogComponent;
import com.micolor.logr.runtime.annotation.LogRecord;
import com.micolor.logr.runtime.component.AnnotationOperateComponent;
import com.micolor.logr.runtime.component.StorageClassInvokeComponent;
import com.micolor.logr.runtime.entity.FieldDetail;
import com.micolor.logr.runtime.entity.LogMessage;
import com.micolor.logr.runtime.entity.StorageData;
import com.micolor.logr.runtime.enums.LogRConfigEnum;
import com.micolor.logr.runtime.enums.OperateTypeEnum;
import com.micolor.logr.runtime.joinpoints.DeleteJoinPoint;
import com.micolor.logr.runtime.joinpoints.InsertJoinPoint;
import com.micolor.logr.runtime.joinpoints.UpdateJoinPoint;
import com.micolor.logr.runtime.properties.LogMq;
import com.micolor.logr.runtime.properties.LogREnumsProperties;
import com.micolor.logr.runtime.properties.LogStorage;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.List;

/**
 * @author EvanGe
 * @Type LogRecordAspect.java
 * @Desc
 * @date 2024/7/2 15:47
 */
@Component
@Aspect
@Configuration
@Slf4j
public class LogRecordAspect {

    @Value("${spring.application.name}")
    private String appName;

    @Resource
    private LogREnumsProperties logREnumsProperties;
    @Resource
    AnnotationOperateComponent annotationOperateComponent;
    @Resource
    InsertJoinPoint insertJoinPoint;
    @Resource
    UpdateJoinPoint updateJoinPoint;
    @Resource
    DeleteJoinPoint deleteJoinPoint;
    @Resource
    StorageClassInvokeComponent storageClassInvokeComponent;

    @Pointcut("@annotation(com.micolor.logr.runtime.annotation.LogRecord)")
    private void pointCut() {
        log.error("LogRecord 切面");
    }

    @Around(value = "pointCut() " +
            "&& @annotation(com.micolor.logr.runtime.annotation.LogRecord)")
    public Object doLog(ProceedingJoinPoint joinPoint) throws Exception {
        Object result = new Object();
        StorageData storageData = new StorageData();
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        //如果方法中添加LogRecord注解
        if (method.isAnnotationPresent(LogRecord.class)) {
            try {
                LogRecord logRecord = method.getAnnotation(LogRecord.class);
                result = joinPoint.proceed();
                LogComponent logComponent = annotationOperateComponent.getLogComponentValue(logRecord);
                LogMessage logMessageTemp = new LogMessage();
                logMessageTemp.setSummary(logComponent.value());
                List<FieldDetail> logFields = annotationOperateComponent.getLogFields(logRecord);
                if (method.isAnnotationPresent(LogRecord.class)) {
                    OperateTypeEnum operateType = logRecord.operate();
                    //为storageData赋值
                    storageData.setOperateType(operateType.getKey());
                    switch (operateType.getKey()) {
                        case "I" : {
                            log.debug("新增操作记录...");
                            storageData.setOperateDesc("新增" + logComponent.value());
                            logMessageTemp.setDescription("新增" + logComponent.value());
                            storageData = insertJoinPoint.joinPoint(storageData, logMessageTemp, logComponent, logFields, result);
                            break;
                        }
                        case "U": {
                            log.debug("更新操作记录...");
                            storageData.setOperateDesc("更新" + logComponent.value());
                            logMessageTemp.setDescription("更新" + logComponent.value());
                            storageData = updateJoinPoint.joinPoint(storageData, logMessageTemp, logComponent, logFields, joinPoint.getArgs(), result);
                            break;
                        }
                        case "D": {
                            log.debug("删除操作记录...");
                            storageData.setOperateDesc("删除" + logComponent.value());
                            logMessageTemp.setDescription("删除" + logComponent.value());
                            storageData = deleteJoinPoint.joinPoint(storageData, logMessageTemp, logComponent, logFields, result);
                            break;
                        }
                        case "Q": {
                            log.debug("查询操作记录，暂时不做处理...");
                            break;
                        }
                        default: {
                            log.debug("其他操作记录，暂时不做处理...");
                            break;
                        }
                    }
                }
            } catch (Throwable e) {
                log.error("记录日志异常:{}", e.getMessage());
            } finally {
                //最后持久化信息
                //log.warn("storageData=>{}", storageData);
                //获取以类方式存储数据的内容




                LogStorage storage = logREnumsProperties.getStorage();
                if (storage.isEnable()) {
                    log.debug("以类方式存储数据");
                    storageClassInvokeComponent.saveLogData(storage.getInitCls(), storageData);
                }
                //获得以MQ方式存储数据的内容
                LogMq mq = logREnumsProperties.getMq();
                if (mq.isEnable()) {
                    log.debug("以MQ方式存储数据,目前暂未实现，请使用类方式存储自定义处理");
                }
            }
        }
        return result;
    }
}
